//
//  Problem33.swift
//  TestProject 33. 搜索旋转排序数组
//
//  Created by 武侠 on 2020/8/21.
//  Copyright © 2020 zhulong. All rights reserved.
//

import UIKit

/*
 33. 搜索旋转排序数组
 假设按照升序排序的数组在预先未知的某个点上进行了旋转。
 ( 例如，数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

 搜索一个给定的目标值，如果数组中存在这个目标值，则返回它的索引，否则返回 -1 。
 你可以假设数组中不存在重复的元素。
 你的算法时间复杂度必须是 O(log n) 级别。

 示例 1:
 输入: nums = [4,5,6,7,0,1,2], target = 0
 输出: 4
 
 示例 2:
 输入: nums = [4,5,6,7,0,1,2], target = 3
 输出: -1
 */
@objcMembers  class Problem33: NSObject {
    func solution() {
//        print(search([4,5,6,7,0,1,2], 0))
//        print(search([4,5,6,7,0,1,2], 3))
        print(search([1,3], 3))
//
//        print(search([3,1], 1))
    }
    
    // 思路：使用二分法，因为在mid处，肯定有一边是有序的
    // 4 5 6 7 0 1 2 3
    // 假如mid = 6的位置： 4 5  和 7 0 1 2 3 // 左边是有序的
    // 假如mid = 1的位置： 4 5 6 7 0 和  2 3 // 后边是有序的
    // 那么：
    // 1: 先判断哪边是有序的: nums[0] < nums[mid]
    // 2: 判断target是否在有序的这边，在的话，继续二分，不在也继续二分（这里类似递归了）
    func search(_ nums: [Int], _ target: Int) -> Int {
        if nums.count == 0 {
            return -1
        }
        if nums.count == 1 {
            return nums[0] == target ? 0 : -1
        }
        
        var l = 0                   // Left
        var r = nums.count - 1      // Right
        while l <= r {
            let mid = (l + r) / 2
            print("mid = ", mid)
            if nums[mid] == target {        // 找到了
                return mid
            }
            // 1: 判断哪边是有序的
            if nums[l] <= nums[mid] {        // 左边是有序的
                // 2: 判断target是否在左边
                if nums[l] <= target && target < nums[mid] {
                    // 在有序的左边
                    r = mid - 1
                } else {
                    // 不在有序的左边
                    l = mid + 1         // 这里类似递归了，得到的子数组还需要判断
                }
            } else {                        // 右边是有序的
                // 2: 判断target是否在右边
                if nums[mid] < target && target <= nums[r] {
                    // 在有序的右边
                    l = mid + 1
                } else {
                    // 不在有序的右边
                    r = mid - 1         // 这里类似递归了，得到的子数组还需要判断
                }
            }
        }
        
        return -1
    }
}
